/*
 * @Author: gggg 1263457581@qq.com
 * @Date: 2025-06-18 18:05:30
 * @LastEditors: gggg 1263457581@qq.com
 * @LastEditTime: 2025-06-18 18:05:51
 * @FilePath: /algorithm-and-data-struct/socket/EventLoopReactor.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <memory>
#include <map>
#include <functional>
#include <thread>
#include <condition_variable>
#include <bits/socket.h>
#include <sys/socket.h>
#include <cstdio>
#include <netinet/in.h>

class TcpConnection;
using TcpConnectionPtr = std::shared_ptr<TcpConnection>;

class EventLoop {
public:
    using Callable_t = std::function<void()>;

    EventLoop();
    ~EventLoop();

    void run();
    void stop();

    void addTask(Callable_t task);
    int createSocket(int port); // 创建监听 socket
    void registerReadEvent(int fd, Callable_t readCallback);

private:
    std::thread m_thread;
    std::vector<Callable_t> m_tasks;
    std::mutex m_mutex;
    std::condition_variable m_condition;
    bool m_running;

    int m_epollFd;
    struct epoll_event m_events[1024];
    std::map<int, Callable_t> m_readCallbacks;
};

int EventLoop::createSocket(int port) {
    int listenFd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenFd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    int opt = 1;
    setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    fcntl(listenFd, F_SETFL, O_NONBLOCK);

    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(listenFd, (sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(listenFd, SOMAXCONN) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    return listenFd;
}

void EventLoop::registerReadEvent(int fd, Callable_t readCallback) {
    epoll_event ev{};
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;

    if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, fd, &ev) == -1) {
        perror("epoll_ctl: add failed");
        close(fd);
        return;
    }

    m_readCallbacks[fd] = std::move(readCallback);
}
void EventLoop::run() {
    m_epollFd = epoll_create1(0);
    if (m_epollFd < 0) {
        perror("epoll_create1");
        exit(EXIT_FAILURE);
    }

    while (m_running) {
        // 处理异步任务
        std::vector<Callable_t> tasks;
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_condition.wait(lock, [this]{ return !m_tasks.empty() || !m_running; });
            if (!m_running) break;
            tasks.swap(m_tasks);
        }

        for (const auto& task : tasks) {
            task();
        }

        // 等待 I/O 事件
        int numEvents = epoll_wait(m_epollFd, m_events, 1024, 0);
        for (int i = 0; i < numEvents; ++i) {
            int fd = m_events[i].data.fd;
            if (m_readCallbacks.count(fd)) {
                m_readCallbacks[fd]();  // 触发对应的读回调
            }
        }
    }
}